/*-------------------------------------------------------------------------
 *
 * dependency.h
 *	  支持对象之间依赖关系的例程。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/catalog/dependency.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef DEPENDENCY_H
#define DEPENDENCY_H

#include "catalog/objectaddress.h"


/*
 * 依赖关系的精确语义由 DependencyType 代码指定
 * （该代码存储在 pg_depend 的 "char" 字段中，
 * 因此我们将 ASCII 码值分配给枚举成员）。
 *
 * 在所有情况下，依赖关系表明被引用的对象在不删除
 * 依赖对象的情况下，不能被删除。
 * 然而，还有几个子类型；有关详细信息，请参见
 * catalogs.sgml 中 pg_depend 的描述。
 */

typedef enum DependencyType
{
	DEPENDENCY_NORMAL = 'n',
	DEPENDENCY_AUTO = 'a',
	DEPENDENCY_INTERNAL = 'i',
	DEPENDENCY_PARTITION_PRI = 'P',
	DEPENDENCY_PARTITION_SEC = 'S',
	DEPENDENCY_EXTENSION = 'e',
	DEPENDENCY_AUTO_EXTENSION = 'x'
} DependencyType;

/*
 * 还有一个 SharedDependencyType 枚举类型，确定 pg_shdepend 
 * 中条目的确切语义。就像常规依赖条目一样，任何 pg_shdepend 
 * 条目意味着被引用的对象不能被删除，除非同时删除
 * 依赖对象。然而，还有一些附加规则：
 *
 * (a) SHARED_DEPENDENCY_OWNER 条目意味着被引用对象是
 * 拥有依赖对象的角色。被引用对象必须是
 * pg_authid 条目。
 *
 * (b) SHARED_DEPENDENCY_ACL 条目意味着被引用对象是
 * 在依赖对象的 ACL 字段中提到的角色。被引用
 * 对象必须是 pg_authid 条目。（对于对象的所有者，
 * 不会创建 SHARED_DEPENDENCY_ACL 条目；因此两个对象可能
 * 由一个或另一个，但不能同时由这两种依赖类型链接。）
 *
 * (c) SHARED_DEPENDENCY_POLICY 条目意味着被引用对象是
 * 在策略对象中提到的角色。被引用对象必须是
 * pg_authid 条目。
 *
 * (d) SHARED_DEPENDENCY_TABLESPACE 条目意味着被引用
 * 对象是在没有存储的关系中提到的表空间。被引用
 * 对象必须是 pg_tablespace 条目。（具有存储的关系不需要
 * 这个：它们受到表空间中物理文件存在的保护。）
 *
 * SHARED_DEPENDENCY_INVALID 是一种用于内部例程的参数
 * 的值，且在目录中无效。
 */
typedef enum SharedDependencyType
{
	SHARED_DEPENDENCY_OWNER = 'o',
	SHARED_DEPENDENCY_ACL = 'a',
	SHARED_DEPENDENCY_POLICY = 'r',
	SHARED_DEPENDENCY_TABLESPACE = 't',
	SHARED_DEPENDENCY_INVALID = 0
} SharedDependencyType;


/* 可扩展的 ObjectAddresses 列表（在 dependency.c 中为私有） */
typedef struct ObjectAddresses ObjectAddresses;

/*
 * 该枚举涵盖所有可能出现在
 * pg_depend.classId 或 pg_shdepend.classId 中的系统目录的 OID。保持 object_classes[] 的同步。
 */
typedef enum ObjectClass
{
	OCLASS_CLASS,				/* pg_class */
	OCLASS_PROC,				/* pg_proc */
	OCLASS_TYPE,				/* pg_type */
	OCLASS_CAST,				/* pg_cast */
	OCLASS_COLLATION,			/* pg_collation */
	OCLASS_CONSTRAINT,			/* pg_constraint */
	OCLASS_CONVERSION,			/* pg_conversion */
	OCLASS_DEFAULT,				/* pg_attrdef */
	OCLASS_LANGUAGE,			/* pg_language */
	OCLASS_LARGEOBJECT,			/* pg_largeobject */
	OCLASS_OPERATOR,			/* pg_operator */
	OCLASS_OPCLASS,				/* pg_opclass */
	OCLASS_OPFAMILY,			/* pg_opfamily */
	OCLASS_AM,					/* pg_am */
	OCLASS_AMOP,				/* pg_amop */
	OCLASS_AMPROC,				/* pg_amproc */
	OCLASS_REWRITE,				/* pg_rewrite */
	OCLASS_TRIGGER,				/* pg_trigger */
	OCLASS_SCHEMA,				/* pg_namespace */
	OCLASS_STATISTIC_EXT,		/* pg_statistic_ext */
	OCLASS_TSPARSER,			/* pg_ts_parser */
	OCLASS_TSDICT,				/* pg_ts_dict */
	OCLASS_TSTEMPLATE,			/* pg_ts_template */
	OCLASS_TSCONFIG,			/* pg_ts_config */
	OCLASS_ROLE,				/* pg_authid */
	OCLASS_DATABASE,			/* pg_database */
	OCLASS_TBLSPACE,			/* pg_tablespace */
	OCLASS_FDW,					/* pg_foreign_data_wrapper */
	OCLASS_FOREIGN_SERVER,		/* pg_foreign_server */
	OCLASS_USER_MAPPING,		/* pg_user_mapping */
	OCLASS_DEFACL,				/* pg_default_acl */
	OCLASS_EXTENSION,			/* pg_extension */
	OCLASS_EVENT_TRIGGER,		/* pg_event_trigger */
	OCLASS_PARAMETER_ACL,		/* pg_parameter_acl */
	OCLASS_POLICY,				/* pg_policy */
	OCLASS_PUBLICATION,			/* pg_publication */
	OCLASS_PUBLICATION_NAMESPACE,	/* pg_publication_namespace */
	OCLASS_PUBLICATION_REL,		/* pg_publication_rel */
	OCLASS_SUBSCRIPTION,		/* pg_subscription */
	OCLASS_TRANSFORM			/* pg_transform */
} ObjectClass;

#define LAST_OCLASS		OCLASS_TRANSFORM

/* performDeletion/performMultipleDeletions 的标志位： */
#define PERFORM_DELETION_INTERNAL			0x0001	/* 内部操作 */
#define PERFORM_DELETION_CONCURRENTLY		0x0002	/* 并发删除 */
#define PERFORM_DELETION_QUIETLY			0x0004	/* suppress notices */
#define PERFORM_DELETION_SKIP_ORIGINAL		0x0008	/* 保持原始对象 */
#define PERFORM_DELETION_SKIP_EXTENSIONS	0x0010	/* 保持扩展 */
#define PERFORM_DELETION_CONCURRENT_LOCK	0x0020	/* 带有
													 * 并发锁模式的正常删除 */


/* 在 dependency.c 中 */

extern void AcquireDeletionLock(const ObjectAddress *object, int flags);

extern void ReleaseDeletionLock(const ObjectAddress *object);

extern void performDeletion(const ObjectAddress *object,
							DropBehavior behavior, int flags);

extern void performMultipleDeletions(const ObjectAddresses *objects,
									 DropBehavior behavior, int flags);

extern void recordDependencyOnExpr(const ObjectAddress *depender,
								   Node *expr, List *rtable,
								   DependencyType behavior);

extern void recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
											Node *expr, Oid relId,
											DependencyType behavior,
											DependencyType self_behavior,
											bool reverse_self);

extern ObjectClass getObjectClass(const ObjectAddress *object);

extern ObjectAddresses *new_object_addresses(void);

extern void add_exact_object_address(const ObjectAddress *object,
									 ObjectAddresses *addrs);

extern bool object_address_present(const ObjectAddress *object,
								   const ObjectAddresses *addrs);

extern void record_object_address_dependencies(const ObjectAddress *depender,
											   ObjectAddresses *referenced,
											   DependencyType behavior);

extern void sort_object_addresses(ObjectAddresses *addrs);

extern void free_object_addresses(ObjectAddresses *addrs);

/* 在 pg_depend.c 中 */

extern void recordDependencyOn(const ObjectAddress *depender,
							   const ObjectAddress *referenced,
							   DependencyType behavior);

extern void recordMultipleDependencies(const ObjectAddress *depender,
									   const ObjectAddress *referenced,
									   int nreferenced,
									   DependencyType behavior);

extern void recordDependencyOnCurrentExtension(const ObjectAddress *object,
											   bool isReplace);

extern void checkMembershipInCurrentExtension(const ObjectAddress *object);

extern long deleteDependencyRecordsFor(Oid classId, Oid objectId,
									   bool skipExtensionDeps);

extern long deleteDependencyRecordsForClass(Oid classId, Oid objectId,
											Oid refclassId, char deptype);

extern long deleteDependencyRecordsForSpecific(Oid classId, Oid objectId,
											   char deptype,
											   Oid refclassId, Oid refobjectId);

extern long changeDependencyFor(Oid classId, Oid objectId,
								Oid refClassId, Oid oldRefObjectId,
								Oid newRefObjectId);

extern long changeDependenciesOf(Oid classId, Oid oldObjectId,
								 Oid newObjectId);

extern long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
								 Oid newRefObjectId);

extern Oid	getExtensionOfObject(Oid classId, Oid objectId);
extern List *getAutoExtensionsOfObject(Oid classId, Oid objectId);

extern bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId);
extern List *getOwnedSequences(Oid relid);
extern Oid	getIdentitySequence(Oid relid, AttrNumber attnum, bool missing_ok);

extern Oid	get_index_constraint(Oid indexId);

extern List *get_index_ref_constraints(Oid indexId);

/* 在 pg_shdepend.c 中 */

extern void recordSharedDependencyOn(ObjectAddress *depender,
									 ObjectAddress *referenced,
									 SharedDependencyType deptype);

extern void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId,
											 int32 objectSubId);

extern void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner);

extern void changeDependencyOnOwner(Oid classId, Oid objectId,
									Oid newOwnerId);

extern void recordDependencyOnTablespace(Oid classId, Oid objectId,
										 Oid tablespace);

extern void changeDependencyOnTablespace(Oid classId, Oid objectId,
										 Oid newTablespaceId);

extern void updateAclDependencies(Oid classId, Oid objectId, int32 objectSubId,
								  Oid ownerId,
								  int noldmembers, Oid *oldmembers,
								  int nnewmembers, Oid *newmembers);

extern bool checkSharedDependencies(Oid classId, Oid objectId,
									char **detail_msg, char **detail_log_msg);

extern void shdepLockAndCheckObject(Oid classId, Oid objectId);

extern void copyTemplateDependencies(Oid templateDbId, Oid newDbId);

extern void dropDatabaseDependencies(Oid databaseId);

extern void shdepDropOwned(List *relids, DropBehavior behavior);

extern void shdepReassignOwned(List *relids, Oid newrole);

#endif							/* DEPENDENCY_H */
